using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

using Advent.aiDevices;

namespace Advent.Controls
{
    public partial class EchoGen : UserControl
    {
        /// <summary>
        /// Contains the graphical controls used to represent a tap
        /// in the echo generator
        /// </summary>
        private class Tap
        {
            public TextBox Delay;
            public TextBox Gain;
            public CheckBox Enabled;
            public Tap()
            {
                Delay = new TextBox();
                Gain = new TextBox();
                Enabled = new CheckBox();
                Enabled.Text = "Enable";


            }
            /// <summary>
            /// parses this particulart set of user controls and returns the corresponding Echo
            /// </summary>
            public Echo Parse()
            {
                double GainAbs;
                double DelayMs;

                if (!double.TryParse(Delay.Text, out DelayMs)) throw new Exception("Invalid delay " + Delay.Text);
                if (!double.TryParse(Gain.Text, out GainAbs)) throw new Exception("Invalid gain " + Gain.Text);
                if (!Enabled.Checked) return null;
                return new Echo(TimeInterval.InMilliseconds(DelayMs), UnitlessQuantity.InAbsolute(GainAbs));
            }
        }

        EchoGenerator Echos= null; 
        private List<Tap> Taps = new List<Tap>(3);


        public EchoGen()
        {
            InitializeComponent();

            this.Layout += new LayoutEventHandler(EchoCtrl_Layout);
            this.EnabledChanged += new EventHandler(EchoCtrl_EnabledChanged);
        }

        void EchoCtrl_EnabledChanged(object sender, EventArgs e)
        {
            timer_Update.Enabled = Enabled;
        }

        /// <summary>
        /// Arranges the controls on the screen
        /// </summary>
        void EchoCtrl_Layout(object sender, LayoutEventArgs e)
        {
            const int Margin = 8;
            const int TextWidth = 80;

            int X = lbl_Delay.Left;
            int Y = lbl_Gain.Top + lbl_Gain.Height + Margin;

            for (int i = 0; i < Taps.Count; i++)
            {
                Tap T = Taps[i];
                T.Delay.Location = new Point(X, Y);
                T.Delay.Width = TextWidth;

                T.Gain.Location = new Point(X + TextWidth + Margin, Y);
                T.Gain.Width = TextWidth;
                if (i == 0) lbl_Gain.Left = T.Gain.Left;
                T.Enabled.Location = new Point(T.Gain.Left + TextWidth + Margin, Y);

                Y += T.Delay.Height + Margin;
            }
        }


        public void SetGenerator(EchoGenerator EchoGen)
        {

            // Dispose of any prior echo generator objects

            foreach(Tap T in Taps)
            {
                Controls.Remove(T.Delay);
                Controls.Remove(T.Gain);
                Controls.Remove(T.Enabled);
                T.Delay.Dispose();
                T.Gain.Dispose();
                T.Enabled.Dispose();
            }
            Taps.Clear();
            Taps = new List<Tap>(3);


            this.Echos = EchoGen;
            for (int i = 0; i < EchoGen.TapCount; i++)
            {
                Tap T = new Tap();
                Controls.Add(T.Delay);
                Controls.Add(T.Gain);
                Controls.Add(T.Enabled);
                Taps.Add(T);
            }
            PerformLayout();
            RefreshControls();
        }

        /// <summary>
        /// Copies the contents of the echo generator to the displayed controls
        /// </summary>
        private void RefreshControls()
        {
            try
            {
                if (Echos == null) return;
                for (int i = 0; i < Taps.Count; i++)
                {
                    Tap T = Taps[i];
                    Echo E = Echos.GetEcho(i);

                    if (E != null)
                    {
                        double Gain = E.Gain.ToAbsolute().Value;
                        if (Gain != 0)
                        {
                            T.Delay.Text = E.Delay.ValueInMilliseconds.ToString();
                            T.Gain.Text = Gain.ToString();
                            T.Enabled.Checked = true;
                            continue;
                        }
                    }
                    T.Delay.Text = "0";
                    T.Gain.Text = "0";
                    T.Enabled.Checked = false;
                }
            }
            catch
            {
            }
        }

        private void AMCtrl_Load(object sender, EventArgs e)
        {
      
        }

        private void timer_Update_Tick(object sender, EventArgs e)
        {
            try
            {
                if (Echos == null) return;
                lbl_IsActive.Text = Echos.IsActive.ToString();
            }
            catch
            {
            }
        }

        private void btn_Generate_Click(object sender, EventArgs e)
        {
            try
            {
                // We parse each of the echo definitions in the controls
                // and update the generator
                for (int i = 0; i < Taps.Count; i++)
                {
                    Echos.SetEcho(i, Taps[i].Parse());
                }
                Echos.Generate();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            } finally {
                RefreshControls();
            }

        }

        private void btn_Stop_Click(object sender, EventArgs e)
        {
            try
            {
                Echos.StopGenerator();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }

        private void btn_resetToDefaults_Click(object sender, EventArgs e)
        {
            try
            {
                Echos.ResetToDefaults();
                RefreshControls();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }
    }
}
